package controllers

import (
	"crypto/md5"
	"fmt"
	"os"
	"reflect"
	"time"

	"math/rand"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego/plugins/cors"
	_ "github.com/go-sql-driver/mysql"
)

/* account to be index*/
var VerCodes map[string]*vcode_t
var CustomerVerCodes map[string]*vcode_t
var ps = fmt.Sprintf
var SidLife int64
var TimeNow int64 = 0
var TimeNowStr string = "2006-01-02 15:04:05"
var conf = beego.AppConfig.String

/* code 3-success 5-error*/
type Recv struct {
	Code int
	Msg  string
	Data interface{}
}

/* store vcode*/
type vcode_t struct {
	code     string
	lasttime int64
}

type Loginuser struct {
	SessionId string
	UserId    int64
	Account   string
	Nick      string
	Headurl   string
	Phone     string
	Email     string
	Coin      float64 // ipfs币
	Flag      int
	LastTime  int64
}

func init() {
	//MysqlInit()
	ArgInit()
	OriginInit()
	TimenowInit()
	FileInit()

	return
}

func log(format string, v ...interface{}) {
	fmt.Println(fmt.Sprintf("[debug][%s]", TimeNowStr), fmt.Sprintf(format, v...))
	return
}

func StrToMD5(str string) (result string) {
	md5Ctx1 := md5.New()
	md5Ctx1.Write([]byte(str))
	result = ps("%x", md5Ctx1.Sum(nil))
	return
}

func MysqlInit() {
	//orm.Debug = false
	var maxIdle int = 30
	var maxConn int = 30
	orm.RegisterDataBase("default", "mysql", conf("mysql"), maxIdle, maxConn)
	log("mysql init success")
	return
}

func ArgInit() {
	SidLife, _ = beego.AppConfig.Int64("sidlife")
	if SidLife == 0 {
		SidLife = 250000 // 3天左右
	}

	// 捕获panic异常
	defer func() {
		if err := recover(); err != nil {
			log("panic: %v", err)
		}
	}()
	VerCodes = make(map[string]*vcode_t)
	CustomerVerCodes = make(map[string]*vcode_t)
	return
}

func FileInit() {
	log("File init begin")
	beego.SetStaticPath("/static", "static")
	beego.SetStaticPath("/xfyun/yin", conf("xfyunpath"))

	err := os.MkdirAll(conf("xfyunpath"), os.ModePerm)
	if err != nil {
		log("xfyun文件夹创建失败:%s", err.Error())
	}

	log("File init success.")
	return
}

func TimenowInit() {
	go func() {
		for {
			tim_t := time.Now()
			TimeNow = tim_t.Unix()
			TimeNowStr = tim_t.Format("2006-01-02 15:04:05")
			time.Sleep(time.Second)
			for key, codee := range VerCodes {
				if TimeNow-codee.lasttime >= 5*60 {
					delete(VerCodes, key)
				}
			}
			for key, codee := range CustomerVerCodes {
				if TimeNow-codee.lasttime >= 5*60 {
					delete(VerCodes, key)
				}
			}

		}
	}()
	return
}

func OriginInit() {
	beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
		AllowAllOrigins:  true,
		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowHeaders:     []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
		ExposeHeaders:    []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
		AllowCredentials: true,
	}))
	log("OriginInit init success")
	return
}

func CheckArg(a ...interface{}) bool {
	for _, arg := range a {
		switch reflect.TypeOf(arg).Kind() {
		case reflect.String:
			if arg.(string) == "" {
				return false
			}
		case reflect.Int64:
			if arg.(int64) == 0 {
				return false
			}
		case reflect.Int32:
			if arg.(int32) == 0 {
				return false
			}
		case reflect.Int:
			if arg.(int) == 0 {
				return false
			}
		case reflect.Float64:
			if arg.(float64) < 0.000001 && arg.(float64) > -0.000001 {
				return false
			}
		case reflect.Float32:
			if arg.(float32) < 0.000001 && arg.(float32) > -0.000001 {
				return false
			}
		default:
			return false
		}
	}
	return true
}

//生成随机字符串
func GetRandomS(size int) string {
	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	bytes := []byte(str)
	result := []byte{}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < size; i++ {
		result = append(result, bytes[r.Intn(len(bytes))])
	}
	return string(result)
}
